package edu.ycu.aladdin.collector.detail;

import edu.ycu.aladdin.collector.CrawlerConfigPool;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import us.codecraft.webmagic.Site;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;

/**
 * UserInfo-Agent pool 的Redis实现.
 *
 * @author <a href="mailto:wangruihuano@gmail.com">王瑞环</a>
 * @see Site
 * @since 1.0
 */
@Slf4j
@Component
public class RedisCrawlerConfigPool implements CrawlerConfigPool {

    private final RedisTemplate<String, Object> redisTemplateWithBasicSerializer;

    public static final Site DEFAULT_SITE = Site.me().setRetryTimes(3).setSleepTime(10000);

    /**
     * agent 池, 其中键为值的hashcode
     */
    private Map<Object, Object> pool;

    public RedisCrawlerConfigPool(RedisTemplate<String, Object> redisTemplateWithBasicSerializer) {
        this.redisTemplateWithBasicSerializer = redisTemplateWithBasicSerializer;
        init();
    }

    private void init() {
        this.pool = redisTemplateWithBasicSerializer.opsForHash().entries(AGENTS_POOL_KEY);
        log.debug("init agent pool is:{}", this.pool);
        if (this.pool == null) {
            this.pool = new HashMap<>();
        }
    }

    @Override
    public Site generateRandomSite() {

        Object[] keys = pool.keySet().toArray();

        if (keys != null && keys.length > 0) {

            int i = new Random().nextInt(keys.length);
            return (Site) pool.get(keys[i]);
        }
        return null;
    }

    @Override
    public void addConfig(Site site) {
        String hashCode = String.valueOf(site.hashCode());
        this.pool.put(hashCode, site);
        redisTemplateWithBasicSerializer.opsForHash().put(AGENTS_POOL_KEY, hashCode, site);
    }

    @Override
    public void delConfig(Site site) {
        String hashCode = String.valueOf(site.hashCode());
        Object remove = this.pool.remove(hashCode);
        if (remove != null) {
            redisTemplateWithBasicSerializer.opsForHash().delete(AGENTS_POOL_KEY, hashCode);
        }
    }

    @Override
    public void delConfig(String hashcode) {
        Object remove = this.pool.remove(hashcode);
        if (remove != null) {
            redisTemplateWithBasicSerializer.opsForHash().delete(AGENTS_POOL_KEY, hashcode);
        }
    }

    @Override
    public Site[] getAll(){
        return pool.values().toArray(new Site[pool.size()]);
    }

    @Override
    public Map<Object, Object> getPool() {
        return pool;
    }

    @Override
    public Site getAgent(String agentId) {
        return (Site) pool.get(agentId);
    }
}
